package com.solarEngine;

import com.motu.vertx.module.utility.kafka.KafkaManager;
import com.motu.vertx.module.utility.toolset.Tool;
import io.vertx.core.Vertx;
import io.vertx.core.json.JsonObject;
import io.vertx.kafka.client.producer.KafkaProducer;
import io.vertx.kafka.client.producer.KafkaProducerRecord;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.common.serialization.StringSerializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Properties;

/**
 * 魔兔BI数据管理类
 */
public class SolarEngineBase {

	//相关文档:https://help.solar-engine.com/cn/docs/Koumhl#2b9f7dd52bb582eff8840d3359be9058

	private static final Logger logger = LoggerFactory.getLogger(SolarEngineBase.class);
	public static KafkaProducer<String, String> bi_producer;
	public static final String KAFKA_TOPIC_BI = "log_solarEngine";

	// 事件名称
	public static final String EVENT_REGISTER = "_mpReg";//注册事件
	public static final String EVENT_LOGIN = "_mpLogin";//登录事件
	public static final String EVENT_CHARGE = "_mpOrder";//充值事件


	/**
	 * 初始化魔兔BIkafka配置（需要在进程初始化调用）
	 *
	 * @param vertx
	 * @param appConfig
	 */
	public static void init(Vertx vertx, JsonObject appConfig) {
		// 游戏行为事件 kafka地址
		String address = appConfig.getString("log-solarEngine-kafka-address");
		if (!Tool.isEmpty(address)) {
			Properties bi_config = new Properties();
			bi_config.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, address);
			bi_config.put("key.serializer", StringSerializer.class);
			bi_config.put("value.serializer", StringSerializer.class);
			bi_config.put("acks", "1");
			// 优化kafka生产者配置
			KafkaManager.upgradeProducerConfig(bi_config, appConfig);
			// 创建一个Kafka Producer
			bi_producer = KafkaProducer.create(vertx, bi_config);
			logger.info("SolarEngineManager kafka init success address:{}", address);
		}
	}

	private static String getUrlQuery(String appkey,long curTime){
		String urlQuery = "?timestamp="+curTime+"&sign="+getToken(appkey,curTime);
		return urlQuery;
	}


	/**
	 * 生成token
	 * @param appkey
	 * @param curTime
	 * @return
	 */
	private static String getToken(String appkey,long curTime){
		//sign =   Md5(appkey+timestamp)
		String sign = DigestUtils.md5Hex(appkey+curTime);// 生成MD5签名
		return sign;
	}

	/**
	 * 获取公共参数
	 * @param appKey
	 * @param eventName
	 * @param userId
	 * @param openId
	 * @param ip
	 * @return
	 */
	private static JsonObject getCommonParams(String appKey,String eventName,long userId, String openId,String ip,long curTime) {

		//TODO:以下默认接入国内小游戏版本所需参数
		JsonObject commonParams = new JsonObject();
		commonParams.put("_appkey",appKey );//应用的 16 位 Appkey
		commonParams.put("_event_name", eventName);//事件标识
		commonParams.put("_source_type", "api");//数据来源，通过 API 报送时传 api
		/**
		 * 用户设备ID
		 * iOS：建议传入 IDFV
		 * Android：建议传入 AndroidID
		 * Web：cookie_id （通过当前时间戳+屏幕宽高+uuid随机数+UA 值 md5 后生成）
		 * 小程序/小游戏：建议传入 openid（抖音优先传入openid，其次anonymousopenid）
		 * 鸿蒙：建议传入 ODID
		 */
		commonParams.put("_distinct_id", openId);
		/**
		 * 一.
		 * 小程序/小游戏：
		 * 当 _distinct_id 为openid时传1101。
		 * 当 _distinct_id 为anonymousopenid时传1102。
		 * 当 _distinct_id 为其它ID时传1103。
		 * Web：
		 * 当 _distinct_id 为默认取值时该值为 1001
		 * 当 _distinct_id 为兜底取值时该值为 1002
		 * 当 _distinct_id_type 为自定义值时该值为 1003
		 * 二.
		 * 小程序/小游戏/WEB必填
		 */
		commonParams.put("_distinct_id_type", 1101);
		/**
		 * 账号id与访客id 2选1 必传1个
		 */
		commonParams.put("_account_id", String.valueOf(userId));//账号 ID
//		commonParams.put("_visitor_id", accountId);//访客 ID
		/**
		 * 标识数据唯一性的 ID，用于重复数据排重处理,非必传
		 */
		commonParams.put("_event_id", Tool.getUUID());
		commonParams.put("_ts", curTime);
		/**
		 * 数据存储区域为中国大陆：1
		 * 数据存储区域为非中国大陆：2
		 */
		commonParams.put("_package_type", 1);
		//TODO:对方技术回复小程序获取不到,暂时文档提供的格式写死
		commonParams.put("_ua", "Mozilla/5.0 (iPhone; CPU iPhone OS 13_3_1 like Mac OS X)");
		commonParams.put("_ip", ip);
		return commonParams;
	}

	private static JsonObject getPropertiesParams(String openid,String _platform) {

		//TODO:以下默认接入国内小游戏版本所需参数
		JsonObject properties = new JsonObject();
		properties.put("_openid", openid);
		properties.put("_platform", _platform);
		properties.put("_mp_type", "wechat");
		properties.put("_app_platform", "minigame");
		return properties;
	}

	/***
	 * 登录事件-微信小游戏
	 * @param appKey
	 * @param userId
	 * @param openId
	 * @param platformType
	 * @param ip
	 */
	public static void sendWxLoginEvent(String appKey,long userId,String openId, String platformType,String ip) {
		long curTime = System.currentTimeMillis();
		JsonObject data = getCommonParams(appKey,EVENT_LOGIN, userId, openId,ip,curTime);
		if (data == null) {
			return;
		}
		// 定义事件属性
		JsonObject properties = getPropertiesParams(openId,platformType);
		properties.put("_login_type","WeChat");
		properties.put("_status","success");

		JsonObject params = new JsonObject();
		params.put("urlQuery", getUrlQuery(appKey,curTime));
		params.put("data", data);
		pushToQueue(params);
	}

	/***
	 * 注册事件-微信小游戏
	 * @param appKey
	 * @param userId
	 * @param openId
	 * @param platformType
	 * @param ip
	 */
	public static void sendWxRegisterEvent(String appKey,long userId,String openId, String platformType,String ip) {
		long curTime = System.currentTimeMillis();
		JsonObject data = getCommonParams(appKey,EVENT_REGISTER, userId, openId,ip,curTime);
		if (data == null) {
			return;
		}
		// 定义事件属性
		JsonObject properties = getPropertiesParams(openId,platformType);
		properties.put("_reg_type","WeChat");
		properties.put("_status","success");

		JsonObject params = new JsonObject();
		params.put("urlQuery", getUrlQuery(appKey,curTime));
		params.put("data", data);
		pushToQueue(params);
	}

	/***
	 * 充值事件-微信小游戏
	 * @param appKey
	 * @param userId
	 * @param openId
	 * @param platformType
	 * @param ip
	 * @param orderId
	 * @param money
	 */
	public static void sendWxChargeEvent(String appKey,long userId,String openId, String platformType,String ip, String orderId,
									   double money) {
		long curTime = System.currentTimeMillis();
		JsonObject data = getCommonParams(appKey,EVENT_CHARGE, userId, openId,ip,curTime);
		if (data == null) {
			return;
		}
		// 定义事件属性
		JsonObject properties = getPropertiesParams(openId,platformType);
		properties.put("_pay_amount", money);// 订单金额，单位：元
		properties.put("_order_id", orderId);
		properties.put("_currency_type", "CNY");
		data.put("properties", properties);

		JsonObject params = new JsonObject();
		params.put("urlQuery", getUrlQuery(appKey,curTime));
		params.put("data", data);
		pushToQueue(params);
	}

	/**
	 * 日志发送到消息队列
	 *
	 * @param params 发送参数
	 */
	private static void pushToQueue(JsonObject params) {
		logger.info("solarEngineManager send params:" + params);
		String topicName = KAFKA_TOPIC_BI;
		if (bi_producer == null) {
			logger.error("SolarEngineManager pushDBQueue fail producer is null!! topicName:" + topicName);
			return;
		}
		KafkaProducerRecord<String, String> record = KafkaProducerRecord.create(topicName, params.toString());
		bi_producer.send(record, done -> {
			if (done.failed()) {
				logger.error("SolarEngineManager pushDBQueue fail params:{} cause:{}", params, Tool.getException(done.cause()));
			} else {
//				RecordMetadata recordMetadata = done.result();
			}
		});
	}
}
